#pragma once
#include <deque>
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <boost/thread.hpp>

typedef unsigned int uint;

// TODO: rename ThreadQueue into ThreadSafeQueue
template <class T>
class ThreadQueue
{
public:
	ThreadQueue(){

		_mutex.initialize();
		_terminate = false;
	}
	~ThreadQueue(){
	
		_mutex.destroy();
	}

	ThreadQueue(const ThreadQueue& otherThreadQueue){}

	void append(const T& obj){
		boost::mutex::scoped_lock lock(_mutex);

		_q.push_back(obj);
		_cond.notify_one();
	}

	const T get() {
		boost::mutex::scoped_lock lock(_mutex);
		//boost::unique_lock<boost::mutex> uniqueLock(_mutex);
		// _terminate = false;
		while (_q.empty()) _cond.wait(lock);
	    
		T x = _q.front();
		_q.erase(_q.begin());
	                         
		return x;
	}


	uint size() {
		_mutex.lock();
		uint s = _q.size(); 
		_mutex.unlock();         
		return s;
	}

	bool search(T elementToSearch) {
		_mutex.lock();
		if ( _q.empty() ) {
			_mutex.unlock();
			return false;
		}
		for ( uint i = 0; i < _q.size(); i++ ) {
			if ( _q[i] == elementToSearch ) {
				_mutex.unlock();
				return true;
			}
		}
		_mutex.unlock();
		return false;
	}

	bool empty() {
		_mutex.lock();
		if ( _q.empty() ) {
			_mutex.unlock();
			return true;
		}
		return false;
		_mutex.unlock();
	}

private:
	boost::mutex				_mutex;
	boost::condition_variable	_cond;
	bool						_terminate;
	std::deque<T>				_q;
};
